package com.ad2campaign.engine.utils;

import java.net.URLEncoder;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.web.client.RestTemplate;

import com.ad2campaign.engine.db.model.Node;

public class JobUtils
{

	private static final Logger LOGGER =  Logger.getLogger(JobUtils.class);
	private static int roundRobinCounter=-1;
	
	//This method is common to all nodes..
	public static void stopAllRunningJob(JobOperator jobOperator,String jobName)
	{

		LOGGER.info("*******************************RECIEVED STOP TRAP*********************************");
		LOGGER.info("*                             STOPPING ALL RUNNING JOB                           *");
		LOGGER.info("*                              SCHEDULER EXITING NOW                             *");
		LOGGER.info("**********************************************************************************");
 
	}
	
	
	
	
	 
	public static void allocateJob(String jobName,String parameter,RestTemplate restTemplate,List<Node> nodes)
	{
		LOGGER.info("allocateJob(): Attempting now to start job "+jobName+"["+parameter+"]");
		try
		{
	  		doRestOperation("?param="+URLEncoder.encode(parameter,"UTF-8"), EngineRestOperation.START, nodes, restTemplate, jobName);
	 	} 
		  catch (Exception e) 
		{
		   LOGGER.error("JobUtils.resumedStoppedJobs(): exception occured while starting job "+jobName+"["+parameter+"]", e);
		}
	 
	}
	
	
	/*This method is not multithreaded call to this method must be sequential*/
 	private static int getNextSlave(int numberOfNodes)
	{
		//Select next slave node
		if (roundRobinCounter >= numberOfNodes-1 || roundRobinCounter==-1)
		{
			roundRobinCounter=0;
		}
		else
		{
			roundRobinCounter++;
		}
		
		return roundRobinCounter;
	}
	
		/*This method is not multi-threaded call to this method must be sequential*/
 		public static String  doRestOperation(String restArgs, EngineRestOperation restOperation,List<Node> nodes,RestTemplate restTemplate,String jobName)
		{
			Node selectedNode = nodes.get(getNextSlave(nodes.size()));
		 	String restUrl= restOperation.toRestUrl(selectedNode) + "/"+restArgs;
		
		 	String response =restTemplate.getForObject(restUrl, String.class);
		 	LOGGER.info("JobUtils.doRestOperation(): Executing rest url "+restUrl);
			LOGGER.info("JobUtils.doRestOperation(): "+restOperation.getOperationName()+" response from node "+selectedNode +" is ["+response +"]");
			int attempt=0;
			while (!restOperation.getSuccessResponse().equals(response) && attempt <nodes.size()*2)
			{
				LOGGER.info("JobUtils.doRestOperation(): Attempt["+(attempt+1)+"] Previous ["+restOperation.getOperationName()+"] operation  attempt with node "+selectedNode+" was failed.");
				selectedNode = nodes.get(getNextSlave(nodes.size()));
				LOGGER.info("JobUtils.doRestOperation(): Attempt["+(attempt+1)+"] Now Trying with node "+selectedNode);
 		 		response =restTemplate.getForObject(restUrl, String.class);
 			 	LOGGER.info("JobUtils.doRestOperation(): Executing rest url "+restUrl);
				LOGGER.info("JobUtils.doRestOperation(): Attempt["+(attempt+1)+"] Got "+restOperation.getOperationName()+"] operation response from node "+selectedNode +" is ["+response +"]");
				attempt++;
			}
			
			if (!restOperation.getSuccessResponse().equals(response) )
			{
				LOGGER.error("Critical error,system is unable to "+restOperation.getOperationName()+" job "+jobName+"["+restArgs+"] after "+attempt + " attempt(s)!!");
				return EngineRestOperation.FAIL.getSuccessResponse();
			}
			return restOperation.getSuccessResponse();
  	}
	
}
